﻿package mortal.game.scene3D.map3D
{
    import __AS3__.vec.*;
    import baseEngine.basic.*;
    import baseEngine.core.*;
    import baseEngine.system.*;
    import com.gengine.resource.*;
    import flash.display.*;
    import flash.display3D.*;
    import flash.events.*;
    import flash.geom.*;
    import frEngine.*;
    import frEngine.core.*;
    import frEngine.event.*;
    import frEngine.shader.*;
    import frEngine.shader.filters.*;
    import frEngine.shader.registType.*;
    import frEngine.shader.registType.base.*;
    import mortal.game.*;
    import mortal.game.scene3D.layer3D.*;
    import mortal.game.scene3D.map3D.mapShader.*;

    public class MapBitmap3DRender extends Object
    {
        private var _brickMat0:ShaderBase;
        private var _brickMat1:ShaderBase;
        private var _brickMat2:ShaderBase;
        private var _textureRegister0:FsParam;
        private var _textureRegister1:FsParam;
        private var _textureRegister2:FsParam;
        private var _vmConst0Register:MaxtrixParam;
        private var _fcConstRegister:FcParam;
        private var _hasInitOk:Boolean = false;
        private var _emptyTexture:Texture3D;
        private var _transform:Matrix3D;
        private var _tempVector3d:Vector3D;
        private var cullFace:String = "none";
        private var depthWrite:Boolean = false;
        private var sourceFactor:String = "one";
        private var destFactor:String = "zero";
        private var depthCompare:String = "always";
        private var _scene3d:Scene3D;
        private var surf:FrSurface3D;
        private var _fconst:Vector.<Number>;
        private static var _instance:MapBitmap3DRender;

        public function MapBitmap3DRender()
        {
            this._transform = new Matrix3D();
            this._tempVector3d = new Vector3D(0, 0, 0, 1);
            this._fconst = this.Vector.<Number>([0, 0, 256 / 1024, 256 / 512]);
            this._scene3d = Global3D.scene;
            this._emptyTexture = new Texture3D(new BitmapData(1, 1, false, 4210752), 0);
            this._emptyTexture.immediatelyUpload();
            this._brickMat0 = new ShaderBase("_brickMat0", new MapVertexFilter(), new MapFragmentFilter(new Texture3D(null, 0, TextureFormat.FORMAT_COMPRESSED)));
            this._brickMat0.materialParams.uvRepeat = false;
            FrEventDispatcher.instance.proxyAddEventListener(this._brickMat0, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander0);
            this._brickMat0.buildBytes();
            this._brickMat1 = new ShaderBase("_brickMat1", new MapVertexFilter(), new MapFragmentFilter(new Texture3D(null, 0, TextureFormat.FORMAT_COMPRESSED_ALPHA)));
            this._brickMat1.materialParams.uvRepeat = false;
            FrEventDispatcher.instance.proxyAddEventListener(this._brickMat1, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander1);
            this._brickMat1.buildBytes();
            BottomMapLayer.instance.init();
            this._brickMat2 = new ShaderBase("_brickMat2", new MapVertexFilter(), new MapFragmentFilter(this._emptyTexture));
            this._brickMat2.materialParams.uvRepeat = false;
            FrEventDispatcher.instance.proxyAddEventListener(this._brickMat2, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander2);
            this._brickMat2.buildBytes();
            Global3D.nullAtfTexture.immediatelyUpload();
            return;
        }// end function

        public function reUpload() : void
        {
            this._emptyTexture.reUpload();
            return;
        }// end function

        private function reBuildHander0(event:Event) : void
        {
            this._textureRegister0 = this._brickMat0.getParam("{texture1}", false);
            FrEventDispatcher.instance.proxyRemoveEventListener(this._brickMat0, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander0);
            this._hasInitOk = this._textureRegister1 != null && this._textureRegister2 != null;
            return;
        }// end function

        private function reBuildHander1(event:Event) : void
        {
            this._textureRegister1 = this._brickMat1.getParam("{texture1}", false);
            FrEventDispatcher.instance.proxyRemoveEventListener(this._brickMat1, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander1);
            this._hasInitOk = this._textureRegister0 != null && this._textureRegister2 != null;
            return;
        }// end function

        private function reBuildHander2(event:Event) : void
        {
            this._textureRegister2 = this._brickMat2.getParam("{texture1}", false);
            this._vmConst0Register = this._brickMat2.getParam("{transform}", true);
            this._fcConstRegister = this._brickMat2.getParam("{F_const}", false);
            FrEventDispatcher.instance.proxyRemoveEventListener(this._brickMat2, Engine3dEventName.MATERIAL_REBUILDER, this.reBuildHander2);
            this._hasInitOk = this._textureRegister0 != null && this._textureRegister1 != null;
            return;
        }// end function

        private function initSurf() : void
        {
            var _loc_1:Number = NaN;
            var _loc_2:Number = NaN;
            var _loc_3:Vector.<Number> = null;
            if (!this.surf)
            {
                _loc_1 = MapConst.pieceWidth;
                _loc_2 = MapConst.pieceHeight;
                this.surf = new FrSurface3D("quad");
                this.surf.addVertexData(FilterName_ID.POSITION_ID, 3, false, null);
                this.surf.addVertexData(FilterName_ID.UV_ID, 2, false, null);
                _loc_3 = this.surf.getVertexBufferByNameId(FilterName_ID.POSITION_ID).vertexVector;
                _loc_3.push(0, 0, 0, 0, 0);
                _loc_3.push(_loc_1, 0, 0, 1, 0);
                _loc_3.push(0, _loc_2, 0, 0, 1);
                _loc_3.push(_loc_1, _loc_2, 0, 1, 1);
                this.surf.indexVector = new Vector.<uint>;
                this.surf.indexVector.push(0, 1, 2, 3, 2, 1);
            }
            return;
        }// end function

        public function draw(param1:Vector.<MapBitmap3D>) : void
        {
            var _loc_4:ShaderBase = null;
            var _loc_14:Texture3D = null;
            var _loc_15:Texture3D = null;
            var _loc_17:Program3D = null;
            if (!this.surf)
            {
                this.initSurf();
            }
            var _loc_2:* = param1.length;
            if (_loc_2 == 0)
            {
                return;
            }
            var _loc_3:* = param1[0];
            _loc_4 = this._brickMat2;
            if (!this._hasInitOk)
            {
                Global3D.drawCalls2d = 0;
                return;
            }
            if (!_loc_4.hasPrepared(null, this.surf))
            {
                return;
            }
            var _loc_5:* = this._scene3d.context;
            var _loc_6:* = this._brickMat2.materialParams.program;
            if (!_loc_6)
            {
                return;
            }
            var _loc_7:* = BottomMapLayer.instance;
            this.drawImp(this.surf, _loc_6);
            if (_loc_7._curMapTexture.texture)
            {
                _loc_5.setTextureAt(1, _loc_7._curMapTexture.texture);
            }
            else
            {
                _loc_5.setTextureAt(1, Global3D.nullAtfTexture.texture);
            }
            var _loc_8:* = _loc_7._offsetX;
            var _loc_9:* = _loc_7._offsetY;
            var _loc_10:* = _loc_7._bgMapWidth;
            var _loc_11:* = _loc_7._bgMapHeight;
            var _loc_12:* = Game.scene.gameCamera.zoom;
            this._fconst[2] = 256 / _loc_10 * _loc_12;
            this._fconst[3] = 256 / _loc_11 * _loc_12;
            var _loc_13:int = 0;
            var _loc_16:int = 0;
            while (_loc_16 < _loc_2)
            {
                
                _loc_3 = param1[_loc_16];
                if (_loc_3.cellTexture)
                {
                    _loc_14 = _loc_3.cellTexture;
                    if (_loc_14.texture == null)
                    {
                        if (_loc_13 < 2)
                        {
                            Texture3D(_loc_14).immediatelyUpload();
                            _loc_13++;
                        }
                        else
                        {
                            _loc_15 = MapVague.instance.loadPiece(_loc_3.info);
                            if (_loc_15)
                            {
                                _loc_14 = _loc_15;
                            }
                            else
                            {
                                _loc_14 = this._emptyTexture;
                            }
                        }
                    }
                }
                else
                {
                    _loc_15 = MapVague.instance.loadPiece(_loc_3.info);
                    if (_loc_15)
                    {
                        _loc_14 = _loc_15;
                    }
                    else
                    {
                        _loc_14 = this._emptyTexture;
                    }
                }
                if (_loc_14.format == TextureFormat.FORMAT_COMPRESSED)
                {
                    _loc_17 = this._brickMat0.materialParams.program.program;
                    var _loc_18:* = _loc_17;
                    ShaderBase.pro = _loc_17;
                }
                else if (_loc_14.format == TextureFormat.FORMAT_COMPRESSED_ALPHA)
                {
                    _loc_17 = this._brickMat1.materialParams.program.program;
                    var _loc_18:* = _loc_17;
                    ShaderBase.pro = _loc_17;
                }
                else
                {
                    _loc_17 = this._brickMat2.materialParams.program.program;
                    var _loc_18:* = _loc_17;
                    ShaderBase.pro = _loc_17;
                }
                _loc_5.setTextureAt(0, _loc_14.texture);
                _loc_5.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, this._vmConst0Register.index, _loc_3.world, true);
                this._fconst[0] = (_loc_3.x - _loc_8) / _loc_10 * _loc_12 + 0.5;
                this._fconst[1] = (_loc_3.y - _loc_9) / _loc_11 * _loc_12 + 0.5;
                _loc_5.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, this._fcConstRegister.index, this._fconst);
                _loc_5.drawTriangles(this.surf.indexBufferFr.indexBuffer, 0, -1);
                var _loc_18:* = Global3D;
                var _loc_19:* = Global3D.drawCalls2d + 1;
                _loc_18.drawCalls2d = _loc_19;
                _loc_16++;
            }
            _loc_5.setTextureAt(1, null);
            return;
        }// end function

        public function drawImp(param1:FrSurface3D, param2:FrProgram3D) : void
        {
            var _loc_4:int = 0;
            var _loc_5:int = 0;
            var _loc_8:MaxtrixParam = null;
            var _loc_9:ConstParamBase = null;
            var _loc_10:uint = 0;
            var _loc_13:Vector.<Number> = null;
            var _loc_16:VaParam = null;
            var _loc_17:uint = 0;
            var _loc_18:int = 0;
            var _loc_19:BufferVo = null;
            var _loc_20:VertexBuffer3D = null;
            var _loc_3:* = this._scene3d.context;
            _loc_4 = 0;
            Global3D.usedSamples = 1;
            _loc_3.setCulling(this.cullFace);
            ShaderBase.cullFace = this.cullFace;
            _loc_3.setDepthTest(this.depthWrite, this.depthCompare);
            ShaderBase.depthWrite = this.depthWrite;
            ShaderBase.depthCompare = this.depthCompare;
            _loc_3.setBlendFactors(this.sourceFactor, this.destFactor);
            ShaderBase.sourceFactor = this.sourceFactor;
            ShaderBase.destFactor = this.destFactor;
            _loc_4 = 0;
            var _loc_6:* = param2.VaParamsList;
            _loc_5 = _loc_6.length;
            var _loc_7:* = ShaderBase.buffers;
            while (_loc_4 < _loc_5)
            {
                
                _loc_16 = _loc_6[_loc_4];
                _loc_17 = _loc_16.vertexNameId;
                _loc_18 = _loc_16.index;
                _loc_19 = param1.bufferVoMap[_loc_17];
                _loc_20 = _loc_19.buffer.vertexBuffer;
                _loc_3.setVertexBufferAt(_loc_18, _loc_20, _loc_19.offset, _loc_19.format);
                _loc_7[_loc_18] = _loc_20;
                _loc_4++;
            }
            Global3D.usedBuffers = _loc_5;
            var _loc_11:* = param2.VcParamsConstList;
            _loc_5 = _loc_11.length;
            var _loc_12:* = Context3DProgramType.VERTEX;
            _loc_4 = 0;
            while (_loc_4 < _loc_5)
            {
                
                _loc_9 = _loc_11[_loc_4];
                _loc_13 = _loc_9.value;
                if (_loc_13)
                {
                    _loc_10 = _loc_13.length / 4 >> 0;
                    _loc_3.setProgramConstantsFromVector(_loc_12, _loc_9.index, _loc_13, _loc_10);
                }
                _loc_4++;
            }
            _loc_11 = null;
            var _loc_14:* = param2.FcParamsConstList;
            _loc_5 = _loc_14.length;
            _loc_12 = Context3DProgramType.FRAGMENT;
            _loc_4 = 0;
            while (_loc_4 < _loc_5)
            {
                
                _loc_9 = _loc_14[_loc_4];
                _loc_13 = _loc_9.value;
                if (_loc_13)
                {
                    _loc_10 = _loc_13.length / 4 >> 0;
                    _loc_3.setProgramConstantsFromVector(_loc_12, _loc_9.index, _loc_13, _loc_10);
                }
                _loc_4++;
            }
            var _loc_15:* = param2.paramsMaxtrixList;
            _loc_4 = 0;
            _loc_5 = _loc_15.length;
            while (_loc_4 < _loc_5)
            {
                
                _loc_8 = _loc_15[_loc_4];
                if (_loc_8.value)
                {
                    _loc_3.setProgramConstantsFromMatrix(_loc_8.type, _loc_8.index, _loc_8.value, true);
                }
                _loc_4++;
            }
            return;
        }// end function

        public static function get instance() : MapBitmap3DRender
        {
            if (!_instance)
            {
                _instance = new MapBitmap3DRender;
            }
            return _instance;
        }// end function

    }
}
